---@class Bezier 贝塞尔
---@field p vec3 计算之后的位置
Bezier = class()

---@alias bezier fun(bezier:Bezier):void

---@class bezier_data
---@field type bezier 贝塞尔函数


-- local b = Bezier.obj({
--     type = function(bezier)
--         bezier:bezier3(ui, { x = 200, y = 600 }, { x = 1000, y = 400 })
--         ui.binding.x=bezier.p.x
--         ui.binding.y=bezier.p.y
--     end
-- })

-- GT.timer.obj({
--     callback = function(data, t)
--         b:update(0.01)
--     end,
--     count = -1,
--     delay = 0.01,
--     immediately = true,
-- })



---@param data bezier_data
function Bezier:ctor(data)
	self.t = 0
	self.type = data.type
	self.falg = false
end

---@param data bezier_data
---@return Bezier
function Bezier.obj(data)
	return new(Bezier, data)
end

---缓动
---@param dt number 缓动自增值
---@return Bezier
function Bezier:update(dt)
	self.t = self.t + dt
	if self.t >= 1 then
		self.t = 1
		self.falg = true
	end
	self.type(self)
	self.falg = false
	return self
end

function Bezier:bezier3(obj, p1, p2, p3)
	p1.z = p1.z or 0
	p2.z = p2.z or 0
	p3.z = p3.z or 0

	local mu = self.t
	local mum1, mum12, mu2
	local p = {}
	mu2 = mu * mu
	mum1 = 1 - mu
	mum12 = mum1 * mum1
	p.x = p1.x * mum12 + 2 * p2.x * mum1 * mu + p3.x * mu2
	p.y = p1.y * mum12 + 2 * p2.y * mum1 * mu + p3.y * mu2
	p.z = p1.z * mum12 + 2 * p2.z * mum1 * mu + p3.z * mu2
	self.p = p
	if obj ~= nil then
		obj.x = self.p.x
		obj.y = self.p.y
		if obj.z~=nil then
			obj.z = self.p.z
		end
		
	end
end

function Bezier:bezier4(obj, p1, p2, p3, p4)
	p1.z = p1.z or 0
	p2.z = p2.z or 0
	p3.z = p3.z or 0
	p4.z = p4.z or 0

	local mu = self.t
	local mum1, mum13, mu3;
	local p = {}

	mum1 = 1 - mu
	mum13 = mum1 * mum1 * mum1
	mu3 = mu * mu * mu

	p.x = mum13 * p1.x + 3 * mu * mum1 * mum1 * p2.x + 3 * mu * mu * mum1 * p3.x + mu3 * p4.x
	p.y = mum13 * p1.y + 3 * mu * mum1 * mum1 * p2.y + 3 * mu * mu * mum1 * p3.y + mu3 * p4.y
	if p1.z ~= nil then
		p.z = mum13 * p1.z + 3 * mu * mum1 * mum1 * p2.z + 3 * mu * mu * mum1 * p3.z + mu3 * p4.z
	end
	self.p = p
	if obj ~= nil then
		obj.x = self.p.x
		obj.y = self.p.y
		if obj.z~=nil then
			obj.z = self.p.z
		end
	end
end
